#include "sphere.h"

#include "ray.h"

#include <cmath>
#include <cstdlib>
#include <limits>

namespace raytrace {

Sphere::Sphere(const Vector3& pos, float r, const Material* material)
    : Primitive(pos, material), r_(r) {
}

bool Sphere::IntersectsWith(const Ray& ray, float& d) const {
  const Vector3 v = Vector3::sub(ray.o_, pos_);
	const float b = -Vector3::dot(v, ray.d_);
	float det = (b * b) - Vector3::dot(v, v) + (r_ * r_);
	bool retval = false;
	if (det > 0)
	{
		det = sqrtf(det);
		const float i1 = b - det;
		const float i2 = b + det;
		if (i2 > 0) {
			if (i1 < 0) {
				d = i2;
				retval = true;  // from inside
			} else {
				d = i1;
				retval = true;  // from outside
			}
		}
	}
	return retval;
}

Vector3 Sphere::NormalAt(const Vector3& pt) const {
  Vector3 n = Vector3::sub(pt, pos_);
  n.normalize();
  return n;
}

Vector3 Sphere::GetRandomPoint() const {
  const float theta = drand48() * 2 * M_PI;
  const float u = (drand48() * 2) - 1;

  return Vector3(cosf(theta) * sqrtf(1 - u*u),
                 sinf(theta) * sqrtf(1 - u*u),
                 u);
}
}
